package tr.helper.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import io.vavr.Tuple;
import io.vavr.Tuple3;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
import org.apache.commons.lang3.StringUtils;
import tr.helper.CommonUtil;
import tr.helper.UserHolder;
import tr.helper.auth.GoogleAuthenticatorUtils;
import tr.helper.controller.log.LogController;
import tr.helper.domain.LoginRequest;
import tr.helper.repository.dao.UserDao;
import tr.helper.repository.table.User;
import tr.helper.service.JiuxianService;
import tr.helper.service.TrService;
import tr.helper.view.UserItem;

/**
 * tr-service
 *
 * @author MrYe
 * @date 2022-01-12 18:32
 */
public abstract class SecurityController implements Initializable {

    protected JiuxianService jiuxianService = new JiuxianService();

    protected TrService trService = new TrService();

    protected UserDao userDao = new UserDao();

    public SecurityController() {
        Context.controllers.put(this.getClass().getSimpleName(), this);
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        if (!StringUtils.contains(location.getPath(), "Server")) {
            if (UserHolder.getInstance() == null) {
                CommonUtil.alert(null, "登录超时");
            }
        }
        init(location, resources);
    }

    public abstract void init(URL location, ResourceBundle resources);

    public Tuple3<HttpResponse, String, String> getCookie(UserItem user, LogController log, boolean forceLogin) throws MalformedURLException {
        String cookies = null;
        log.addLog("拉取账号:%s的交易信息", user.getUsername());
        Long time = null;
        User condUser = new User();
        condUser.setId(user.getId());
        User curUser = userDao.select(condUser);
        BeanUtil.copyProperties(curUser, user);
        if (null != curUser.getTokenTime()) {
            time = CommonUtil.diffMinutes(CommonUtil.asLocalDateTime(curUser.getTokenTime()), LocalDateTime.now());
        }
        HttpResponse csResponse = null;
        String token;
        boolean reLogin = (null != time && time >= 20) || curUser.getCookie() == null;
        if (reLogin || forceLogin) {
            // 开始拉取信息
            csResponse = trService.getCsrfToken();
            final String body = csResponse.body();

            List<String> csrfToken = TrService.matchKeyElement(body, "csrf-token");
            token = csrfToken.get(0).trim();
            log.addLog("缓存时间已过:%s 初始令牌:%s", time, token);

            cookies = autoLogin(log, trService, user, cookies, csResponse, token);
        } else {
            cookies = curUser.getCookie();
            token = curUser.getToken();
            log.addLog("账号:%s 使用缓存令牌:%s", user.getUsername(), cookies);
        }
        return Tuple.of(csResponse, token, cookies);
    }

    public String autoLogin(LogController log, TrService trService, UserItem user, String cookies, HttpResponse csResponse, String token) throws MalformedURLException {
        HttpResponse loginResponse;
        String captcha = null;
//        do {
//            loginResponse = trService.getImage(csResponse.getCookies());
//            byte[] imgBt = loginResponse.bodyBytes();
//            Tuple2<File, String> tuple2 = CommonUtil.recogImage(log, imgBt, true);
//            String code = tuple2._2();
//
//            if (tuple2._1 != null) {
//                log.addLog2("获得验证码:" + code, new ImageView(String.valueOf(tuple2._1.toURL())));
//            }
//            captcha = CommonUtil.getNumber(code);
//            log.addLog("识别的验证码:%s 处理后的:%s", code, captcha);
//        } while (StringUtils.length(captcha) < 4);
        loginResponse = trService.login(csResponse, token, LoginRequest.builder().email(user.getUsername()).password(user.getPassword()).sec(user.getSec()).captcha(captcha).build());
        if (loginResponse.getStatus() == 200) {
            cookies = CommonUtil.cookieToString(loginResponse.getCookies());
            User updUser = new User();
            updUser.setId(user.getId());
            updUser.setTokenTime(new Date());
            updUser.setCookie(cookies);
            updUser.setToken(token);
            if (null == user.getSec()) {
                final String sec = trService.getSec(cookies);
                user.setSec(sec);
                updUser.setSec(sec);
                log.addLog("账号:%s 同步安全码:%s", user.getUsername(), sec);

                loginResponse = trService.login(csResponse, token, LoginRequest.builder().email(user.getUsername()).password(user.getPassword()).sec(user.getSec()).build());
                if (loginResponse.getStatus() == 200) {
                    cookies = CommonUtil.cookieToString(loginResponse.getCookies());
                    updUser.setTokenTime(new Date());
                    updUser.setCookie(cookies);
                }
            }
            try {
                // 绑定校验器
                JSONObject bindRet = trService.bindValidator(cookies, token, GoogleAuthenticatorUtils.getTOTPCode(user.getSec()));
                log.addLog("账号:%s %s", user.getUsername(), bindRet.getString("showTitle"));
            } catch (Exception e) {
                log.addLog("账号:%s 绑定校验器异常", user.getUsername());
                e.printStackTrace();
            }

            userDao.updateByPrimaryKey(updUser, user.getId());
            log.addLog("账号:%s登录成功 令牌:%s", user.getUsername(), cookies);
        } else {
            log.addLog("账号:%s登录失败 可能是验证码:%s错误", user.getUsername(), captcha);
            log.addLog("账号:%s开始重新登录", user.getUsername());
            CommonUtil.sleep(500L);
            return autoLogin(log, trService, user, cookies, csResponse, token);
        }
        return cookies;
    }

}
